/**
 * ===========================================
 * 
 * 数据库类封装
 * 		1. 数据库多次连接，消耗资源问题。
 * 		2. 利用单例, 解决实例不共享问题。
 * 
 * ===========================================
 */

const MongoClient = require('mongodb').MongoClient;
const ObjectID = require('mongodb').ObjectID;
const dbConfig = require('./config.js');


class DB {
	
	/**
	 * 静态方法，实现单例
	 */
	static getInstance() {
		if(!DB.instance) {
			DB.instance = new DB();
		}
		return DB.instance;
	}
	
	/**
	 * 构造函数
	 */
	constructor () {
		this.dbClient = '';
		this.connect();  // 实例化时链接数据库
	}
	
	/**
	 * 连接数据库
	 */
	connect () {
		return new Promise((resolve, reject) => {
			if (this.dbClient) {
				resolve(this.dbClient);
				return;
			}
			
			MongoClient.connect(dbConfig.DBUrl, (err, client) => {
				if(err) {
					reject(err);
					return;
				}
				this.dbClient = client.db(dbConfig.dbName);
				resolve(this.dbClient);
			});
		});
	}
	
	/**
	 * id字符串转换成DB数据库使用的ObjectID
	 */
	getObjectID(id){
		return new ObjectID(id);
	}
	
	/**
	 * 查询
	 */
	findOne (collectionName, json) {
		
		let attr = {};
		let index = 0;
		let size = 0;
		let sort = {};
		switch (arguments.length) {
			case 2:
				attr = {};
				index = 0;
				size = 0;
				break;
			case 3:
				if(arguments[2].index){
					attr = {};
					index = ((arguments[2].index || 1) - 1) * (arguments[2].size || 10);
					size = arguments[2].size || 10;

                    sort = (arguments[2].sort) ? arguments[2].sort : {};
				}else if(arguments[2].sort){
					attr = {};
					index = 0;
					size = 0;
					sort = arguments[2].sort;
				}else {
					attr = arguments[2];
					index = 0;
					size = 0;
				}
				break;
			case 4:
				attr = arguments[2];
				index = ((arguments[3].index || 1) - 1) * (arguments[3].size || 10);
				size = arguments[3].size || 10;
                sort = (arguments[3].sort) ? arguments[3].sort : {};
				break;
			default:
				console.log('参数错误');
				break;
		}
		
		return new Promise((resolve, reject) => {
			this.connect().then((db) => {
				//let result = db.collection(collectionName).find(json);
				let result = db.collection(arguments[0]).find(arguments[1], {fields: attr})
								.skip(index)
								.limit(size)
								.sort(sort);
				
				result.toArray((err, docs) => {
					if(err){
						reject(err);
						return;
					}
					resolve(docs);
				});
			});
		});
	}
	
	/**
	 * 增加
	 */
	insertOne (collectionName, json) {
		return new Promise((resolve, reject) => {
			this.connect().then((db) => {
				db.collection(collectionName).insertOne(json, (err, result) => {
					if(err) {
						reject(err);
						return;
					}
					resolve(result);
				});
			});
		});
	}
	
	/**
	 * 修改
	 */
	updateOne (collectionName, json1, json2) {
		return new Promise((resolve, reject) => {
			this.connect().then((db) => {
				
				db.collection(collectionName).updateOne(json1, {
					$set: json2
				}, (err, result) => {
					if(err) {
						reject(err);
						return;
					}
					resolve(result);
				});
			});
		});
	}
	
	/**
	 * 删除
	 */
	deleteOne (collectionName, json) {
		return new Promise((resolve, reject) => {
			this.connect().then((db) => {
				db.collection(collectionName).deleteOne(json, (err, result) => {
					if(err) {
						reject(err);
						return;
					}
					resolve(result);
				});
			});
		});
	}
	
	
	/**
	 * count
	 */
	count (collectionName, json) {
		return new Promise((resolve, reject) => {
			this.connect().then((db) => {
				db.collection(collectionName).count(json, (err, result) => {
					if(err) {
						reject(err);
						return;
					}
					resolve(result);
				});
			});
		});
	}
}


module.exports = DB.getInstance();